package com.leoman.service.impl;

import com.leoman.controller.common.CommonController;
import com.leoman.core.Constant;
import com.leoman.dao.*;
import com.leoman.entity.*;
import com.leoman.entity.vo.CodeVo;
import com.leoman.entity.vo.UserInfoVo;
import com.leoman.exception.*;
import com.leoman.service.CommentService;
import com.leoman.service.PraiseService;
import com.leoman.service.UserCollectService;
import com.leoman.service.UserService;
import com.leoman.utils.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.text.ParseException;
import java.util.*;

/**
 * UserServiceImpl
 * Created by 涂奕恒 on 2016/11/23 0023 下午 4:02.
 */
@Service
public class UserServiceImpl implements UserService {

    public List<CodeVo> voList = new ArrayList<>();

    @Autowired
    private UserDao userDao;

    @Autowired
    private ThirdUserDao thirdUserDao;

    @Autowired
    private FeedBackDao feedBackDao;

    @Autowired
    private UserMoneyDao userMoneyDao;

    @Autowired
    private AttentionDao attentionDao;

    @Autowired
    private LeaveMessageDao leaveMessageDao;

    @Autowired
    private UserLetterMindDao userLetterMindDao;

    @Autowired
    private LetterAnnexSampleDao letterAnnexSampleDao;

    @Autowired
    private PraiseDao praiseDao;

    @Autowired
    private UserCollectDao userCollectDao;

    @Autowired
    private UserSealInfoDao userSealInfoDao;

    @Autowired
    private VersionInfoDao versionInfoDao;

    @Autowired
    private PaperDao paperDao;

    @Autowired
    private BroadcastDao broadcastDao;

    @Autowired
    private MindDao mindDao;

    @Autowired
    private CircleDao circleDao;

    @Autowired
    private CommentService commentService;

    @Autowired
    private UserCollectService userCollectService;

    @Autowired
    private PraiseService praiseService;

    @Override
    public List<User> findAll() {
        return userDao.findAll();
    }

    @Override
    public Page<User> find(int pageNum, int pageSize) {
        return userDao.findAll(new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    @Override
    public Page<User> find(int pageNum) {
        return find(pageNum, Constant.PAGE_DEF_SIZE);
    }

    @Override
    public User getById(int id) {
        return userDao.findOne(id);
    }

    @Override
    public void deleteById(int id) {
        userDao.delete(id);
    }

    @Override
    public User create(User user) {
        return userDao.save(user);
    }

    @Override
    public User update(User user) {
        return userDao.save(user);
    }

    @Override
    @Transactional
    public void deleteAll(int[] ids) {
        for (int id : ids) {
            deleteById(id);
        }
    }

    @Override
    public String sendCode(String mobile, Integer type) throws ParamErrorException, MobileExistException, MobileNotFindException {
        if (StringUtils.isBlank(mobile)) {
            throw new ParamErrorException();
        }

        // 1=注册，2=忘记密码，3=绑定手机号，默认为注册
        if (null == type) {
            type = 1;
        }

        User user = userDao.findOneByMobile(mobile);

        switch (type) {
            case 1:
            case 3:
                if (null != user) {
                    throw new MobileExistException();
                }
                break;
            case 2:
                if (null == user) {
                    throw new MobileNotFindException();
                }
                break;
        }

        // 生成验证码
        String code = RandomUtil.getCode();

        // 发送验证码
        SendMsgUtil.sendMsg(mobile, code, null);

        removeCode(mobile, type);

        // 将生成的验证码保存到voList中
        CodeVo codeVo = new CodeVo();
        codeVo.setMobile(mobile);
        codeVo.setCode(code);
        codeVo.setType(type);
        codeVo.setCreateTime(new Date());

        voList.add(codeVo);

        return code;
    }

    @Override
    public User iRegister(String mobile, String password, String code) throws ParamErrorException, MobileExistException, CodeErrorException {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password) || StringUtils.isBlank(code)) {
            throw new ParamErrorException();
        }

        // 检测验证码是否正确
        if (!checkCode(mobile, code, 1).equals(0)) {
            throw new CodeErrorException();
        }

        User user = userDao.findOneByMobile(mobile);

        if (null != user) {
            throw new MobileExistException();
        }

        removeCode(mobile, 1);

        return setDefaultUser(mobile, Md5Util.md5(password), Constant.USER_TYPE_DEFAULT, "", "", Constant.APP_USER_STATUS_DEFAULT, userDao);
    }

    @Override
    public User iUserLogin(String mobile, String password) throws ParamErrorException, MobileNotFindException, PasswordErrorException, UserSealStatusException {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password)) {
            throw new ParamErrorException();
        }

        User user = userDao.findOneByMobile(mobile);

        if (null == user) {
            throw new MobileNotFindException();
        }

        if (!user.getPassword().equals(Md5Util.md5(password))) {
            throw new PasswordErrorException();
        }

        if (user.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }

        if (null != user.getRegion()) {
            user.setRegionId(user.getRegion().getId());
        }

        return user;
    }

    @Override
    public Integer checkCode(String mobile, String code, Integer type) {
        if (null == type) {
            type = 1;
        }
        Boolean flag = false;
        Integer result = 0;

        try {
            // 检查验证码是否正确，如果不正确，返回错误码
            CodeVo tempCodeVo = null;
            for (CodeVo codeVo : voList) {
                if (codeVo.getCode().equals(code) && codeVo.getMobile().equals(mobile)) {
                    flag = true;
                    tempCodeVo = codeVo;
                }
            }

            // 1=验证码不正确 2=验证码类型不正确 3=验证码超时
            if (!flag) {
                return 1;
            } else if (!tempCodeVo.getType().equals(type)) {
                return 2;
            } else if (DateUtils.secondCompare(tempCodeVo.getCreateTime(), 600)) {
                return 3;
            }

            result = 0;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    @Override
    public User iLoginPlus(String openId, Integer type, String avatar, String nickName, Integer sex) throws ParamErrorException, ThirdTypeErrorException, UserSealStatusException {
        if (StringUtils.isBlank(openId) || null == type) {
            throw new ParamErrorException();
        }

        User user;
        ThirdUser thirdUser = thirdUserDao.findOneByOpenIdAndType(openId, type);

        if (null != thirdUser && !thirdUser.getType().equals(type)) {
            throw new ThirdTypeErrorException();
        }

        if (null == thirdUser) {
            user = setDefaultUser("", "", type, avatar, nickName, sex, userDao);

            thirdUser = new ThirdUser();
            thirdUser.setOpenId(openId);
            thirdUser.setType(type);
            thirdUser.setNickname(nickName);
            thirdUser.setUser(user);

            thirdUserDao.save(thirdUser);
        } else {
            if (null == thirdUser.getUser()) {
                user = setDefaultUser("", "", type, avatar, nickName, sex, userDao);
            } else {
                user = thirdUser.getUser();

                if (StringUtils.isBlank(user.getAvatar())) {
                    user.setAvatar(avatar);
                }
                if (StringUtils.isBlank(user.getNickName())) {
                    user.setNickName(nickName);
                }

                userDao.save(user);
            }
        }

        if (user.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }

        if (null != user.getRegion()) {
            user.setRegionId(user.getRegion().getId());
        }

        return user;
    }

    @Override
    public void iForgetPwd(String mobile, String password, String code) throws ParamErrorException, MobileNotFindException, CodeErrorException, UserSealStatusException {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password) || StringUtils.isBlank(code)) {
            throw new ParamErrorException();
        }

        if (!checkCode(mobile, code, 2).equals(0)) {
            throw new CodeErrorException();
        }

        User user = userDao.findOneByMobile(mobile);

        if (null == user) {
            throw new MobileNotFindException();
        }

        if (user.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }
        user.setPassword(Md5Util.md5(password));
        user.setUpdateTime(System.currentTimeMillis());

        userDao.save(user);

        removeCode(mobile, 2);
    }

    @Override
    public void iBindingMobile(Integer userId, String mobile, String password, String code) throws ParamErrorException, UserNotFindException, MobileExistException, CodeErrorException, UserSealStatusException {
        if (null == userId || StringUtils.isBlank(mobile) || StringUtils.isBlank(password) || StringUtils.isBlank(code)) {
            throw new ParamErrorException();
        }

        if (!checkCode(mobile, code, 3).equals(0)) {
            throw new CodeErrorException();
        }

        User user = getUserInfo(userId, userDao);

        User userByMobile = userDao.findOneByMobile(mobile);

        if (null != userByMobile) {
            throw new MobileExistException();
        }

        user.setMobile(mobile);
        user.setPassword(Md5Util.md5(password));
        user.setUpdateTime(System.currentTimeMillis());

        userDao.save(user);

        removeCode(mobile, 3);
    }

    @Override
    public User iFindOneByInfo(Integer userId) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        User user = getUserInfo(userId, userDao);

        if (null != user.getRegion()) {
            user.setRegionId(user.getRegion().getId());
        }

        user.setFansNum(attentionDao.findFansList(userId).size());
        user.setAttentionNum(attentionDao.findAttentionList(userId).size());
        user.setLeaveNum(leaveMessageDao.findToMyList(userId).size());

        user.setIsNewFans(attentionDao.findFansListNoRead(userId).size());
        user.setIsNewAttention(attentionDao.findAttentionListNoRead(userId).size());
        user.setIsNewLeave(leaveMessageDao.findToMyListNoRead(userId).size());

        user.setIsBindingWeiXin(null == thirdUserDao.findOneByUserIdAndType(userId, Constant.USER_TYPE_WEIXIN) ? Constant.USER_STATUS_NO : Constant.USER_STATUS_YES);
        user.setIsBindingWeiBo(null == thirdUserDao.findOneByUserIdAndType(userId, Constant.USER_TYPE_WEIBO) ? Constant.USER_STATUS_NO : Constant.USER_STATUS_YES);
        user.setIsBindingQQ(null == thirdUserDao.findOneByUserIdAndType(userId, Constant.USER_TYPE_QQ) ? Constant.USER_STATUS_NO : Constant.USER_STATUS_YES);

        return user;
    }

    @Override
    public void iModifyUserInfo(Integer userId, String nickName, String birthday, Integer sex, Integer regionId) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        User user = getUserInfo(userId, userDao);

        if (StringUtils.isNotBlank(nickName)) {
            user.setNickName(nickName);
        }

        if (StringUtils.isNotBlank(birthday)) {
            user.setBirthday(birthday);
        }

        if (null != sex) {
            user.setSex(sex);
        }

        if (null != regionId) {
            Region region = new Region();
            region.setId(regionId);
            user.setRegion(region);
        }

        if (null != user.getRegion()) {
            user.setRegionId(user.getRegion().getId());
        }

        userDao.save(user);
    }

    @Override
    public void iModifyUserPassword(Integer userId, String oldPassword, String newPassword) throws ParamErrorException, OldPasswordErrorException, UserNotFindException, UserSealStatusException {
        if (StringUtils.isBlank(oldPassword) || StringUtils.isBlank(newPassword)) {
            throw new ParamErrorException();
        }

        User user = getUserInfo(userId, userDao);

        if (!user.getPassword().equals(Md5Util.md5(oldPassword))) {
            throw new OldPasswordErrorException();
        }

        user.setPassword(Md5Util.md5(newPassword));
        user.setUpdateTime(System.currentTimeMillis());

        userDao.save(user);
    }

    @Override
    public void iModifyUserAvatar(Integer userId, MultipartRequest multipartRequest) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        User user = getUserInfo(userId, userDao);

        // 获取头像文件
        MultipartFile avatar = multipartRequest.getFile("avatar");
        if (null != avatar && avatar.getSize() > 0) {
            QiNiuUtils.delete(user.getAvatar());
            user.setAvatar(QiNiuUtils.upload(avatar));
        }

        MultipartFile backgroundImage = multipartRequest.getFile("backgroundImage");
        if (null != backgroundImage && backgroundImage.getSize() > 0) {
            QiNiuUtils.delete(user.getBackgroundImage());
            user.setBackgroundImage(QiNiuUtils.upload(backgroundImage));
        }

        userDao.save(user);
    }

    @Override
    public void iApplyMoney(Integer userId, Double money, String account)
            throws ParamErrorException,
            UserNotFindException,
            MoneyShortException,
            ApplyMoneyCountMaxException,
            CreateTimeShortException,
            UserSealStatusException {
        if (null == money || money <= 0) {
            throw new ParamErrorException();
        }

        User user = getUserInfo(userId, userDao);

        if (user.getMoney() < money) {
            throw new MoneyShortException();
        }

        // 限制一：注册软件首月不可以提现
        if (user.getCreateTime() <= DateUtils.dateAddDay(new Date(), -30).getTime()) {
            throw new CreateTimeShortException();
        }

        // 限制二：每周只能进行一次提现
        if (userMoneyDao.findListByParams(userId, DateUtils.dateAddDay(new Date(), -7).getTime()).size() > 0) {
            throw new ApplyMoneyCountMaxException();
        }

        // 限制三：每次提现额度限制在15元以上
        if (money <= 15) {
            throw new ParamErrorException();
        }

        // 修改该用户账户余额
        user.setMoney(user.getMoney() - money);
        userDao.save(user);

        // 新增提现记录
        UserMoney userMoney = new UserMoney();
        userMoney.setUser(user);
        userMoney.setAccount(account);
        userMoney.setType(Constant.USER_MONEY_TYPE_OUT);
        userMoney.setMoney(money);

        userMoneyDao.save(userMoney);
    }

    @Override
    public void iBindingInfo(Integer userId, Integer type, String openId) throws ParamErrorException, UserNotFindException, UserSealStatusException, ThirdExistException {
        if (null == type || StringUtils.isBlank(openId)) {
            throw new ParamErrorException();
        }

        User user = UserServiceImpl.getUserInfo(userId, userDao);

        ThirdUser thirdUser = thirdUserDao.findOneByOpenIdAndType(openId, type);

        if (null != thirdUser) {
            throw new ThirdExistException();
        }

        thirdUser = new ThirdUser();
        thirdUser.setUser(user);
        thirdUser.setType(type);
        thirdUser.setOpenId(openId);

        thirdUserDao.save(thirdUser);
    }

    @Override
    public void iAddFeedBack(Integer userId, String mobile, String content) throws ParamErrorException, UserNotFindException, MobileNotFindException, UserSealStatusException {
        User user = getUserInfo(userId, userDao);

        if (StringUtils.isBlank(mobile) && StringUtils.isBlank(user.getMobile())) {
            throw new MobileNotFindException();
        }

        FeedBack feedBack = new FeedBack();
        feedBack.setUser(user);
        feedBack.setMobile(StringUtils.isBlank(mobile) ? user.getMobile() : mobile);
        feedBack.setContent(content);

        feedBackDao.save(feedBack);
    }

    @SuppressWarnings("unchecked")
    @Override
    public Page<UserInfoVo> iPageByParams(final Integer userId, final String nickName, Integer pageNum, Integer pageSize) {
        Integer[] info = CommonController.getPageParams(pageNum, pageSize);
        PageRequest pageRequest = new PageRequest(info[0] - 1, info[1], Sort.Direction.DESC, "id");

        final Page<User> userPage = userDao.findAll(new Specification<User>() {
            @SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();

                if (StringUtils.isNotBlank(nickName)) {
                    predicateList.add(cb.like(root.get("nickName").as(String.class), "%" + nickName + "%"));
                }

                predicateList.add(cb.equal(root.get("sealStatus").as(Integer.class), Constant.APP_USER_STATUS_DEFAULT));

                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }

                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, pageRequest);

        List<UserInfoVo> list = new ArrayList<>();

        for (User user : userPage.getContent()) {
            list.add(AttentionServiceImpl.getUserInfoVo(user, userId, attentionDao));
        }

        return new PageImpl(list, pageRequest, userPage.getTotalElements());
    }

    @Override
    @Transactional
    public void iAddLeave(Integer userId,
                          Integer sourceId,
                          String content,
                          Integer imgNum/*,
                          MultipartRequest multipartRequest*/) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        if (StringUtils.isBlank(content)/* && (null == imgNum || imgNum == 0)*/) {
            throw new ParamErrorException();
        }

        User user = UserServiceImpl.getUserInfo(userId, userDao);
        User sourceUser = UserServiceImpl.getUserInfo(sourceId, userDao);

        LeaveMessage leaveMessage = new LeaveMessage();

        leaveMessage.setUser(user);
        leaveMessage.setSourceUser(sourceUser);
        leaveMessage.setContent(content);

        leaveMessageDao.save(leaveMessage);

        // 保存留言图片信息
        /*List<MultipartFile> list = new ArrayList<>();

        if (null != imgNum) {
            MultipartFile multipartFile;
            for (int i = 0; i < imgNum; i++) {
                multipartFile = multipartRequest.getFile("file" + i);
                list.add(multipartFile);
            }
        } else {
            list = multipartRequest.getFiles("file");
        }

        Image image;
        for (MultipartFile file : list) {
            if (null != file && file.getSize() > 0) {
                image = new Image();
                image.setUrl(QiNiuUtils.upload(file));
                image.setSourceId(leaveMessage.getId());
                image.setSourceType(Constant.SOURCE_TYPE_LEAVE);

                imageDao.save(image);
            }
        }*/
    }

    @SuppressWarnings("unchecked")
    @Override
    public Page<LetterAnnexSample> iPageLetterAnnexByParams(final Integer userId, final Integer type, Integer pageNum, Integer pageSize) {
        Integer[] info = CommonController.getPageParams(pageNum, pageSize);
        PageRequest pageRequest = new PageRequest(info[0] - 1, info[1], Sort.Direction.DESC, "id");

        final Page<UserLetterMind> userLetterMindPage = userLetterMindDao.findAll(new Specification<UserLetterMind>() {
            @SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
            @Override
            public Predicate toPredicate(Root<UserLetterMind> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();

                predicateList.add(cb.equal(root.get("user").get("id").as(Integer.class), userId));

                predicateList.add(cb.equal(root.get("sourceType").as(Integer.class), 1));

                predicateList.add(cb.equal(root.get("type").as(Integer.class), type));

                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }

                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, pageRequest);

        List<LetterAnnexSample> list = new ArrayList<>();

        for (UserLetterMind userLetterMind : userLetterMindPage.getContent()) {
            list.add(getLetterAnnexSample(userLetterMind));
        }

        return new PageImpl(list, pageRequest, userLetterMindPage.getTotalElements());
    }

    @Override
    public void iPraise(Integer userId,
                        Integer sourceId,
                        Integer sourceType,
                        Integer type)
            throws ParamErrorException,
            UserNotFindException,
            UserSealStatusException,
            PraiseNotFindException,
            PraiseExistException {
        if (null == userId || null == sourceId || null == sourceType || null == type) {
            throw new ParamErrorException();
        }

        User user = UserServiceImpl.getUserInfo(userId, userDao);

        Praise praise = praiseDao.findOneByParams(userId, sourceId, sourceType);

        if (type == 1) {
            // 点赞
            if (null != praise) {
                throw new PraiseExistException();
            }

            praise = new Praise();
            praise.setUser(user);
            praise.setSourceId(sourceId);
            praise.setSourceType(sourceType);

            praiseDao.save(praise);
        } else {
            // 取消赞
            if (null == praise) {
                throw new PraiseNotFindException();
            }

            praiseDao.delete(praise.getId());
        }
    }

    @Override
    public void iCollect(Integer userId,
                         Integer sourceId,
                         Integer sourceType,
                         Integer type)
            throws ParamErrorException,
            UserNotFindException,
            UserSealStatusException,
            CollectNotFindException,
            CollectExistException {
        if (null == userId || null == sourceId || null == sourceType || null == type) {
            throw new ParamErrorException();
        }

        User user = UserServiceImpl.getUserInfo(userId, userDao);

        UserCollect userCollect = userCollectDao.findOneByParams(userId, sourceId, sourceType);

        if (type == 1) {
            // 收藏
            if (null != userCollect) {
                throw new CollectExistException();
            }

            userCollect = new UserCollect();
            userCollect.setUser(user);
            userCollect.setSourceId(sourceId);
            userCollect.setSourceType(sourceType);

            userCollectDao.save(userCollect);
        } else {
            // 取消收藏
            if (null == userCollect) {
                throw new CollectNotFindException();
            }

            userCollectDao.delete(userCollect.getId());
        }
    }

    @Override
    public void iUpdateVersion(String num, MultipartRequest multipartRequest) {
        VersionInfo versionInfo = versionInfoDao.findOne(1);

        if (StringUtils.isNotBlank(num)) {
            versionInfo.setNum(num);
        }

        MultipartFile url = multipartRequest.getFile("apk");
        if (null != url && url.getSize() > 0) {
            QiNiuUtils.delete(versionInfo.getUrl());
            versionInfo.setUrl(QiNiuUtils.upload(url));
        }

        versionInfoDao.save(versionInfo);
    }

    @Override
    public Map<String, Object> iCheckVersion() {
        VersionInfo versionInfo = versionInfoDao.findOne(1);

        Map<String, Object> map = new HashMap<>();
        map.put("num", versionInfo.getNum());
        map.put("url", versionInfo.getUrl());

        return map;
    }

    @Override
    @Transactional
    public void deleteInfo(Integer sourceId, Integer sourceType) throws ParamErrorException {
        if (null == sourceId || null == sourceType) {
            throw new ParamErrorException();
        }

        // 删除对应的评论信息
        commentService.deleteAllComment(sourceId, sourceType);

        // 删除对应的收藏信息
        userCollectService.deleteAllCollect(sourceId, sourceType);

        // 删除对应的点赞信息
        praiseService.deleteAllInfo(sourceId, sourceType);

        switch (sourceType) {
            case 1:
                // 纸条
                Paper paper = paperDao.findOne(sourceId);
                if (null != paper) {
                    paperDao.delete(paper);
                }
                break;
            case 2:
                // 广播
                Broadcast broadcast = broadcastDao.findOne(sourceId);
                if (null != broadcast) {
                    broadcastDao.delete(broadcast);
                }
                break;
            case 3:
                // 心事
                Mind mind = mindDao.findOne(sourceId);
                if (null != mind) {
                    mindDao.delete(mind);
                }
                break;
            case 4:
                // 兴趣圈
                Circle circle = circleDao.findOne(sourceId);
                if (null != circle) {
                    circleDao.delete(circle);
                }
                break;
        }
    }

    @Override
    public Integer recordMoney(Integer userId, Double money, Integer platform) throws ParamErrorException {
        if (null == userId || null == money || null == platform) {
            throw new ParamErrorException();
        }

        User user = new User();
        user.setId(userId);

        UserMoney userMoney = new UserMoney();
        userMoney.setUser(user);
        userMoney.setMoney(money);
        userMoney.setPlatform(platform);

        userMoneyDao.save(userMoney);

        return userMoney.getId();
    }

    @Override
    public Integer findCountWithNewUser(Integer index) {
        try {
            Integer count = 0;
            Long startTime;
            Long endTime;

            try {
                switch (index) {
                    case 0:
                        // 今日新增用户数
                        startTime = DateUtils.getDateWithDay(0, 0).getTime();
                        endTime = DateUtils.getDateWithDay(0, 1).getTime();
                        count = userDao.findListByParams(startTime, endTime).size();
                        break;
                    case 7:
                        // 本周新增用户数
                        startTime = DateUtils.getDateWithDay(-7, 0).getTime();
                        endTime = DateUtils.getDateWithDay(0, 1).getTime();
                        count = userDao.findListByParams(startTime, endTime).size();
                        break;
                    case 30:
                        // 本月新增用户数
                        startTime = DateUtils.getDateWithDay(-30, 0).getTime();
                        endTime = DateUtils.getDateWithDay(0, 1).getTime();
                        count = userDao.findListByParams(startTime, endTime).size();
                        break;
                    case 100:
                        // 总用户数
                        count = userDao.findAll().size();
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public Page<User> pageByParams(final String nickName,
                                   final Integer type,
                                   final String startTime,
                                   final String endTime,
                                   Integer pageNum,
                                   Integer pageSize) {
        return userDao.findAll(new Specification<User>() {
            @SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();

                if (StringUtils.isNotBlank(nickName)) {
                    Predicate pre = cb.like(root.get("nickName").as(String.class), "%" + nickName + "%");
                    predicateList.add(pre);
                }

                if (null != type) {
                    Predicate pre = cb.equal(root.get("type").as(Integer.class), type);
                    predicateList.add(pre);
                }

                if (StringUtils.isNotBlank(startTime)) {
                    try {
                        Long startDate = DateUtils.stringToDateWithFormat(startTime, "yyyy-MM-dd hh:mm:ss").getTime();
                        Predicate pre = cb.gt(root.get("createTime").as(Long.class), startDate);
                        predicateList.add(pre);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }

                if (StringUtils.isNotBlank(endTime)) {
                    try {
                        Long endDate = DateUtils.stringToDateWithFormat(endTime, "yyyy-MM-dd hh:mm:ss").getTime();
                        Predicate pre = cb.lt(root.get("createTime").as(Long.class), endDate);
                        predicateList.add(pre);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }

                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }

                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    @Override
    @Transactional
    public Integer changeUserStatus(Integer[] userIds, Integer status, String content) {
        try {
            User user;
            UserSealInfo userSealInfo;
            for (Integer userId : userIds) {
                user = userDao.findOne(userId);

                if (user.getSealStatus().equals(status)) {
                    continue;
                }

                user.setSealStatus(status);

                userDao.save(user);

                userSealInfo = new UserSealInfo();
                userSealInfo.setUser(user);
                if (StringUtils.isNotBlank(content)) {
                    userSealInfo.setContent(content);
                }

                userSealInfoDao.save(userSealInfo);
            }
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除手机号
     *
     * @param mobile 需要移除的手机号
     * @param type   验证码类型，1=注册，2=忘记密码，3=绑定手机号
     */
    private void removeCode(String mobile, Integer type) {
        if (null == type) {
            type = 1;
        }
        // 如果匹配到了，则移除缓存中的验证码实体信息
        Iterator iterator = voList.iterator();
        CodeVo vo;
        while (iterator.hasNext()) {
            vo = (CodeVo) iterator.next();
            if (vo.getMobile().equals(mobile) && vo.getType().equals(type)) {
                iterator.remove();
            }
        }
    }

    /**
     * 获取用户信息
     *
     * @param userId 用户ID
     * @return 用户信息实体
     * @throws UserNotFindException    参数不正确异常
     * @throws UserNotFindException    找不到用户信息异常
     * @throws UserSealStatusException 用户已被禁用异常
     */
    public static User getUserInfo(Integer userId, UserDao userDao) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        if (null == userId) {
            throw new ParamErrorException();
        }

        User user = userDao.findOne(userId);

        if (null == user) {
            throw new UserNotFindException();
        }

        if (user.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }

        return user;
    }

    /**
     * 设置默认用户信息
     *
     * @param mobile   手机号
     * @param password 密码，MD5大写加密
     * @param type     用户类型
     * @param avatar   头像
     * @param nickName 昵称
     * @param sex      性别，0=男，1=女
     * @param userDao  用户Dao层
     * @return 用户信息
     */
    public static User setDefaultUser(String mobile, String password, Integer type, String avatar, String nickName, Integer sex, UserDao userDao) {
        User user = new User();
        user.setMobile(mobile);
        user.setPassword(password);
        user.setType(type);
        user.setAvatar(avatar);
        user.setSex(sex);
        user.setNickName(nickName);

        userDao.save(user);

        return user;
    }

    /**
     * 将用户购买记录转化为信件附属信息
     *
     * @param userLetterMind 用户购买记录
     * @return 信件附属信息
     */
    private LetterAnnexSample getLetterAnnexSample(UserLetterMind userLetterMind) {
        return letterAnnexSampleDao.findOneByLetterAnnexId(userLetterMind.getSourceId());
    }
}